package com.czwj.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.czwj.dao.EquipmentMapper;
import com.czwj.dao.PressureMapper;
import com.czwj.entities.Equipment;
import com.czwj.entities.Pressure;
import com.czwj.util.SpringUtils;

public class OilPressureSocket extends Thread {

	PressureMapper pressureMapper = SpringUtils.getBean(PressureMapper.class);
	EquipmentMapper equipmentMapper = SpringUtils.getBean(EquipmentMapper.class);
	SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
	SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	static DecimalFormat df = new DecimalFormat("0000");
	static final String BLANKHEADER = "2A53444C4A47";
	static final String REQUIREDATA = "2A52444C44415441230D0A";
	public static Map<String, Socket> socketMap = new HashMap<String, Socket>();
	public static Pattern pattern = Pattern.compile(
			"\\*00\\d{15}\\d{12}[W|N]\\d{4}[E|G]{2}\\d{4}[E|G]\\d{4}[E|G]\\d{4}[E|G][N|S|0]\\d{8}[E|W|0]\\d{9}[+|-|0]\\d{9}\\d000000\\#");
	public static Pattern errorDataPattern = Pattern.compile(
			"[@|$]{3}\\d{15}");
	public static Pattern requiredPattern = Pattern.compile(
			"\\*01\\d{15}\\d{12}[W|N]\\d{4}[E|G]{2}\\d{4}[E|G]\\d{4}[E|G]\\d{4}[E|G][N|S|0]\\d{8}[E|W|0]\\d{9}[+|-|0]\\d{9}\\d000000\\#");
	private ServerSocket ss;

	public OilPressureSocket(Integer port) {
		try {
			ss = new ServerSocket(port);
			System.out.println("Socket服务启动成功，端口：" + port);
		} catch (IOException e) {
			System.out.println("初始化Socket服务异常:\n");
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		try {
			while (true) {
				Socket socket = ss.accept();
				socket.setKeepAlive(true);
				new SocketThread(socket).start();
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("Socket运行中出现了异常：\n");
		}
	}

	class SocketThread extends Thread {
		private String _imei = "";
		private InputStream inStream = null;
		private byte[] receivBuf = new byte[100];
		private String acceptCont;// 接收信息
		private Socket socket;
		private String data ="";

		public SocketThread(Socket socket) throws IOException {
			inStream = socket.getInputStream();
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				while (inStream.read(receivBuf) != -1) {
					// 接收内容为16进制字符串
					acceptCont = new String(receivBuf).trim();
					receivBuf = new byte[100];
					if(acceptCont.startsWith("*")) {
						if(acceptCont.endsWith("#")) {
							InsertThread insertThread = new InsertThread(acceptCont);
							Thread thread = new Thread(insertThread);
							thread.start();
							data ="";
						}else {
							data =acceptCont;
						}
					}else {
						if(acceptCont.endsWith("#")) {
							data+=acceptCont;
							InsertThread insertThread = new InsertThread(data);
							Thread thread = new Thread(insertThread);
							thread.start();
							data ="";
						}else {
							data+=acceptCont;
						}
					}
					
					yield();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				if (socketMap.get(_imei) != null) {
					Socket socket = socketMap.get(_imei);
					socketMap.remove(_imei);
					Equipment equipment = equipmentMapper.findByCode(_imei);
					equipment.setWorkstatus(0);
					equipmentMapper.updateByPrimaryKeySelective(equipment);
					Pressure pressure = new Pressure();
					pressure.setWorkstatus("N");
					pressure.setDate(new Date());
					pressure.setImei(_imei);
					pressure.setEquipmentid(equipment.getId());
					pressureMapper.insertSelective(pressure);
					try {
						socket.close();
						System.out.println(_imei + "已关闭");
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
						System.out.println(_imei + "关闭异常");
					}
				}
			}

		}

		class InsertThread implements Runnable {
			private String data;

			public InsertThread(String data) {
				this.data = data;
			}

			@Override
			public void run() {
				System.out.println();
				System.out.println("接收数据"+sdf2.format(new Date())+":"+data);
				Matcher matcher= errorDataPattern.matcher(data);
				while(matcher.find()) {
					String header = matcher.group();
					data.replace(header, "");
				}
				String[] arr = data.split("\\*");
				for (String string : arr) {
					string = "*"+string;
					matcher = pattern.matcher(string);
					if (matcher.find()) {
						try {
							String str = matcher.group();
							System.out.println("解析定时数据"+sdf2.format(new Date())+":"+str);
							System.out.println("----------------");
							System.out.println();
							String imei = data.substring(3, 18);
							Equipment equipment = equipmentMapper.findByCode(imei);
							if(equipment==null) {
								continue;
							}
							Integer equipmentid = -1;
							equipmentid = equipment.getId();
							if (socketMap.get(imei) == null) {
								socketMap.put(imei, socket);
								_imei = imei;
								System.out.println("IMEI:"+_imei+"注册");
							}
							Date date = sdf.parse(data.substring(18, 30));
							// System.out.println(sdf2.format(date));
							String workstatus = data.substring(30, 31);
							// System.out.println(workstatus);
							Integer timeblank = Integer.parseInt(data.substring(31, 35));
							// System.out.println(timeblank);
							String chipstatus = data.substring(35, 36);
							// System.out.println(chipstatus);
							String rotatestatus = data.substring(36, 37);
							String pushstatus = data.substring(41, 42);

							String mudstatus = data.substring(46, 47);

							Integer version = Integer.parseInt(data.substring(81, 82));
							Double rotate = 0d;
							Double push = 0d;
							Double mud = 0d;
							if(version ==1 ) {
								rotate = Double.valueOf(data.substring(37, 41)) / 2000 * 40;
								push = Double.valueOf(data.substring(42, 46)) / 2000 * 40;
								mud = Double.valueOf(data.substring(47, 51)) / 2000 * 40;
							}else if (version == 2) {
								rotate = Double.valueOf(data.substring(37, 41)) / 100;
								push = Double.valueOf(data.substring(42, 46)) / 100;
								mud = Double.valueOf(data.substring(47, 51)) / 100;
							}
							String gpsstatus = data.substring(51, 52);
							// System.out.println(gpsstatus);
							Double latitude = 0d;
							Double longitude = 0d;
							if(!data.substring(52, 53).equals("0")) {
								latitude = (data.substring(52, 53).equals("N") ? 1 : -1)
										* (Double.valueOf(data.substring(53, 61))) / 1000000;
							}
							if(!data.substring(61, 62).equals("0")) {
								longitude = (data.substring(61, 62).equals("E") ? 1 : -1)
										* (Double.valueOf(data.substring(62, 71))) / 1000000;
							}
							// System.out.println(latitude);
							// System.out.println(longitude);
							Double height = (data.substring(71, 72).equals("+") ? 1 : -1)
									* (Double.valueOf(data.substring(72, 77))) / 10;
							// System.out.println(height);
							Double speed = Double.valueOf(data.substring(77, 81)) / 10;
							// System.out.println(speed);
							
							// System.out.println(version);
							Pressure pressure = new Pressure(imei, equipmentid, rotatestatus, rotate, pushstatus, push,
									mudstatus, mud, date, workstatus, timeblank, chipstatus, gpsstatus, longitude, latitude,
									height, speed, version);
							pressureMapper.insertSelective(pressure);
							if(workstatus.equals("W")&&equipment.getWorkstatus()==0) {
								equipment.setWorkstatus(1);
								equipmentMapper.updateByPrimaryKeySelective(equipment);
							}else if (workstatus.equals("N")&&equipment.getWorkstatus()==1) {
								equipment.setWorkstatus(0);
								equipmentMapper.updateByPrimaryKeySelective(equipment);
							}
							continue;
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					matcher = requiredPattern.matcher(string);
					if (matcher.find()) {
						try {
							String str = matcher.group();
							System.out.println("解析请求数据"+sdf2.format(new Date())+":"+str);
							System.out.println("----------------");
							System.out.println();
							String imei = data.substring(3, 18);
							Equipment equipment = equipmentMapper.findByCode(imei);
							if(equipment==null) {
								continue;
							}
							Integer equipmentid = -1;
							equipmentid = equipment.getId();
							if (socketMap.get(imei) == null) {
								socketMap.put(imei, socket);
								_imei = imei;
								System.out.println("IMEI:"+_imei+"注册");
							}
							Date date = sdf.parse(data.substring(18, 30));
							// System.out.println(sdf2.format(date));
							String workstatus = data.substring(30, 31);
							// System.out.println(workstatus);
							Integer timeblank = Integer.parseInt(data.substring(31, 35));
							// System.out.println(timeblank);
							String chipstatus = data.substring(35, 36);
							String rotatestatus = data.substring(36, 37);
							String pushstatus = data.substring(41, 42);

							String mudstatus = data.substring(46, 47);

							Integer version = Integer.parseInt(data.substring(81, 82));
							Double rotate = 0d;
							Double push = 0d;
							Double mud = 0d;
							if(version ==1 ) {
								rotate = Double.valueOf(data.substring(37, 41)) / 2000 * 40;
								push = Double.valueOf(data.substring(42, 46)) / 2000 * 40;
								mud = Double.valueOf(data.substring(47, 51)) / 2000 * 40;
							}else if (version == 2) {
								rotate = Double.valueOf(data.substring(37, 41)) / 10;
								push = Double.valueOf(data.substring(42, 46)) / 10;
								mud = Double.valueOf(data.substring(47, 51)) / 10;
							}
							String gpsstatus = data.substring(51, 52);
							// System.out.println(gpsstatus);
							Double latitude = 0d;
							Double longitude = 0d;
							if(!data.substring(52, 53).equals("0")) {
								latitude = (data.substring(52, 53).equals("N") ? 1 : -1)
										* (Double.valueOf(data.substring(53, 61))) / 1000000;
							}
							if(!data.substring(61, 62).equals("0")) {
								longitude = (data.substring(61, 62).equals("E") ? 1 : -1)
										* (Double.valueOf(data.substring(62, 71))) / 1000000;
							}
							// System.out.println(latitude);
							// System.out.println(longitude);
							Double height = (data.substring(71, 72).equals("+") ? 1 : -1)
									* (Double.valueOf(data.substring(72, 77))) / 10;
							// System.out.println(height);
							Double speed = Double.valueOf(data.substring(77, 81)) / 10;
							// System.out.println(speed);
							// System.out.println(version);
							Pressure pressure = new Pressure(imei, equipmentid, rotatestatus, rotate, pushstatus, push,
									mudstatus, mud, date, workstatus, timeblank, chipstatus, gpsstatus, longitude, latitude,
									height, speed, version);
							pressureMapper.insertSelective(pressure);
							if(workstatus.equals("W")&&equipment.getWorkstatus()==0) {
								equipment.setWorkstatus(1);
								equipmentMapper.updateByPrimaryKeySelective(equipment);
							}else if (workstatus.equals("N")&&equipment.getWorkstatus()==1) {
								equipment.setWorkstatus(0);
								equipmentMapper.updateByPrimaryKeySelective(equipment);
							}
							continue;
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
//					pattern = Pattern.compile("@{3}\\d{15}");
//					matcher = pattern.matcher(data);
//					if (matcher.find()) {
//						String str = matcher.group();
//						str = str.replace("@@@", "");
//						if (socketMap.get(str) == null) {
//							System.err.println(str);
//							socketMap.put(str, socket);
//							imei = str;
//							Equipment equipment = equipmentMapper.findByCode(imei);
//							equipment.setWorkstatus(1);
//							equipmentMapper.updateByPrimaryKeySelective(equipment);
//						}
//						return;
//					}
				}
				
			}
		}
	}

	public static void sendTimeBlank(Socket socket, Integer blank) {
		try {
			OutputStream outputStream = socket.getOutputStream();
			String order = BLANKHEADER + convertStringToHex(df.format(blank)) + "230D0A";
			System.err.println(order);
			outputStream.write(toBytes(order));
			outputStream.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static boolean requirePressureData(Socket socket) {
		try {
			OutputStream outputStream = socket.getOutputStream();
			String order = REQUIREDATA;
			System.err.println(order);
			outputStream.write(toBytes(order));
			outputStream.flush();
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	private static byte[] toBytes(String str) {
		if (str == null || str.trim().equals("")) {
			return new byte[0];
		}

		byte[] bytes = new byte[str.length() / 2];
		for (int i = 0; i < str.length() / 2; i++) {
			String subStr = str.substring(i * 2, i * 2 + 2);
			bytes[i] = (byte) Integer.parseInt(subStr, 16);
		}

		return bytes;
	}

	private static String convertStringToHex(String str) {

		char[] chars = str.toCharArray();

		StringBuffer hex = new StringBuffer();
		for (int i = 0; i < chars.length; i++) {
			hex.append(Integer.toHexString(chars[i]).toUpperCase());
		}

		return hex.toString();
	}
}
